#include "stdafx.h"


#ifndef ARRAYSIZE
#define ARRAYSIZE(x) sizeof(x)/sizeof(x[0])
#endif



BOOL IsSQLCEUpdateRequired()
{
  BOOL bRes = TRUE;
  // Check registry for post cold boot install of SQLCE v3.5
  HKEY hKey=NULL;
  DWORD dwType=REG_SZ, dwLength=0, dwDisp=0;
  LONG lRes=0;
  lRes = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("\\Software\\Microsoft\\Microsoft SQL Server Compact Edition\\v3.5"), 0, 0, &hKey);

  if (lRes != ERROR_SUCCESS) {
    bRes=TRUE;
  } else
    bRes=FALSE;

  return bRes;
}

//BOOL DeleteSQLCABs(LPTSTR lpszInstallDir) 
//{
//  BOOL bRes = TRUE;
//  WCHAR file[MAX_PATH], buf[MAX_PATH];
//  StringCchPrintf(buf, ARRAYSIZE(buf), _T("%s\\SQLCE*.CAB"), lpszInstallDir);
//  WIN32_FIND_DATA fd;
//  HANDLE hFind = FindFirstFile(buf, &fd);
//  if (INVALID_HANDLE_VALUE != hFind) 
//  {
//    StringCchPrintf(file, ARRAYSIZE(file), _T("%s\\%s"), lpszInstallDir, fd.cFileName);
//    DeleteFile(file);
//    while (FindNextFile(hFind, &fd) != 0)
//    {
//      StringCchPrintf(file, ARRAYSIZE(file), _T("%s\\%s"), lpszInstallDir, fd.cFileName);
//      DeleteFile(file);
//    }
//    FindClose(hFind);
//  }
//  return bRes;
//}

void CleanupAppRegKey(LPCTSTR lpszParentKey, LPCTSTR lpszSubKey)
{
    HKEY hKey;

    if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, 
                                      lpszParentKey,
                                      0,
                                      KEY_ALL_ACCESS,
                                      &hKey))
    {
        RegDeleteKey(hKey, lpszSubKey);
        RegCloseKey(hKey);
    }
}

#define UPGRADEFILE L"\\__AVIANPLAY_UPGRADE.DAT"
#define UP_DBFILE L"\\AvianPlay.sdf"
#define UP_INI_CONTROLS L"\\INI\\Controls.ini"
#define UP_INI_EVENTS L"\\INI\\Events.ini"
#define UP_INI_LIBRARY L"\\INI\\Library.ini"
#define UP_INI_PODCASTS L"\\INI\\Podcasts.ini"
#define UP_INI_REGEX L"\\INI\\RegEx.ini"
#define UP_INI_SETTINGS L"\\INI\\Settings.ini"
#define UP_INI_STATE L"\\INI\\State.ini"
#define UP_CACHE_MUSIC L"\\NPMusic.apcache"
#define UP_CACHE_PODCAST L"\\NPPodcast.apcache"
#define UP_CACHE_RADIO L"\\NPRadio.apcache"
#define UP_CACHE_EDITOR L"\\NPEditor.apcache"
#define UP_ERROR_LOG L"\\Error.log"

#define UP_DBFILE_TEMP L"\\__AvianPlay.sdf"
#define UP_INI_CONTROLS_TEMP L"\\INI\\__Controls.ini"
#define UP_INI_EVENTS_TEMP L"\\INI\\__Events.ini"
#define UP_INI_LIBRARY_TEMP L"\\INI\\__Library.ini"
#define UP_INI_PODCASTS_TEMP L"\\INI\\__Podcasts.ini"
#define UP_INI_REGEX_TEMP L"\\INI\\__RegEx.ini"
#define UP_INI_SETTINGS_TEMP L"\\INI\\__Settings.ini"
#define UP_INI_STATE_TEMP L"\\INI\\__State.ini"
#define UP_CACHE_MUSIC_TEMP L"\\__NPMusic.apcache"
#define UP_CACHE_PODCAST_TEMP L"\\__NPPodcast.apcache"
#define UP_CACHE_RADIO_TEMP L"\\__NPRadio.apcache"
#define UP_CACHE_EDITOR_TEMP L"\\__Editor.apcache"
#define UP_ERROR_LOG_TEMP L"\\__Error.log"

void MoveFile(LPCTSTR pszInstallDir, LPCTSTR src, LPCTSTR dest)
{
  wchar_t srcPath[MAX_PATH+1];
  wchar_t destPath[MAX_PATH+1];

  _tcscpy(srcPath, pszInstallDir);
  _tcscat(srcPath, src);

  _tcscpy(destPath, pszInstallDir);
  _tcscat(destPath, dest);

  SetFileAttributes(srcPath, FILE_ATTRIBUTE_NORMAL);
  MoveFile(srcPath, destPath);
}

void DeleteFile(LPCTSTR pszInstallDir, LPCTSTR path)
{
  wchar_t dpath[MAX_PATH+1];
  _tcscpy(dpath, pszInstallDir);
  _tcscat(dpath, path);
  SetFileAttributes(dpath, FILE_ATTRIBUTE_NORMAL);
  DeleteFile(dpath);
}

void ClearUpgrade(LPCTSTR pszInstallDir)
{
  wchar_t path[MAX_PATH+1];
  _tcscpy(path, pszInstallDir);
  _tcscat(path, UPGRADEFILE);
  SetFileAttributes(path, FILE_ATTRIBUTE_NORMAL);
  DeleteFile(path);
}

void SetUpgrade(LPCTSTR pszInstallDir)
{
  // Clear existing upgrade (just in case -- gets rid of attributes)
  ClearUpgrade(pszInstallDir);

  // Create the upgrade notification file
  wchar_t path[MAX_PATH+1];
  _tcscpy(path, pszInstallDir);
  _tcscat(path, UPGRADEFILE);
  fclose(_wfopen(path, L"w+"));

  // Move the data files, so they aren't written over
  MoveFile(pszInstallDir, UP_DBFILE, UP_DBFILE_TEMP);
  MoveFile(pszInstallDir, UP_INI_CONTROLS, UP_INI_CONTROLS_TEMP);
  MoveFile(pszInstallDir, UP_INI_EVENTS, UP_INI_EVENTS_TEMP);
  MoveFile(pszInstallDir, UP_INI_LIBRARY, UP_INI_LIBRARY_TEMP);
  MoveFile(pszInstallDir, UP_INI_PODCASTS, UP_INI_PODCASTS_TEMP);
  MoveFile(pszInstallDir, UP_INI_REGEX, UP_INI_REGEX_TEMP);
  MoveFile(pszInstallDir, UP_INI_SETTINGS, UP_INI_SETTINGS_TEMP);
  MoveFile(pszInstallDir, UP_INI_STATE, UP_INI_STATE_TEMP);
  MoveFile(pszInstallDir, UP_CACHE_MUSIC, UP_CACHE_MUSIC_TEMP);
  MoveFile(pszInstallDir, UP_CACHE_PODCAST, UP_CACHE_PODCAST_TEMP);
  MoveFile(pszInstallDir, UP_CACHE_RADIO, UP_CACHE_RADIO_TEMP);
  MoveFile(pszInstallDir, UP_CACHE_EDITOR, UP_CACHE_EDITOR_TEMP);
  MoveFile(pszInstallDir, UP_ERROR_LOG, UP_ERROR_LOG_TEMP);
}

void ResetUpgrade(LPCTSTR pszInstallDir)
{
  ClearUpgrade(pszInstallDir);
  DeleteFile(pszInstallDir, UP_DBFILE_TEMP);
  DeleteFile(pszInstallDir, UP_INI_CONTROLS_TEMP);
  DeleteFile(pszInstallDir, UP_INI_EVENTS_TEMP);
  DeleteFile(pszInstallDir, UP_INI_LIBRARY_TEMP);
  DeleteFile(pszInstallDir, UP_INI_PODCASTS_TEMP);
  DeleteFile(pszInstallDir, UP_INI_REGEX_TEMP);
  DeleteFile(pszInstallDir, UP_INI_SETTINGS_TEMP);
  DeleteFile(pszInstallDir, UP_INI_STATE_TEMP);
  DeleteFile(pszInstallDir, UP_CACHE_MUSIC_TEMP);
  DeleteFile(pszInstallDir, UP_CACHE_PODCAST_TEMP);
  DeleteFile(pszInstallDir, UP_CACHE_RADIO_TEMP);
  DeleteFile(pszInstallDir, UP_CACHE_EDITOR_TEMP);
  DeleteFile(pszInstallDir, UP_ERROR_LOG_TEMP);
}

void UnsetUpgrade(LPCTSTR pszInstallDir)
{
  // Remove the ugprade notification file
  ClearUpgrade(pszInstallDir);

  // Remove the default files
  DeleteFile(pszInstallDir, UP_DBFILE);
  DeleteFile(pszInstallDir, UP_INI_CONTROLS);
  DeleteFile(pszInstallDir, UP_INI_EVENTS);
  DeleteFile(pszInstallDir, UP_INI_LIBRARY);
  DeleteFile(pszInstallDir, UP_INI_PODCASTS);
  DeleteFile(pszInstallDir, UP_INI_REGEX);
  DeleteFile(pszInstallDir, UP_INI_SETTINGS);
  DeleteFile(pszInstallDir, UP_INI_STATE);
  DeleteFile(pszInstallDir, UP_CACHE_MUSIC);
  DeleteFile(pszInstallDir, UP_CACHE_PODCAST);
  DeleteFile(pszInstallDir, UP_CACHE_RADIO);
  DeleteFile(pszInstallDir, UP_CACHE_EDITOR);
  DeleteFile(pszInstallDir, UP_ERROR_LOG);

  // Move the data files back
  MoveFile(pszInstallDir, UP_DBFILE_TEMP, UP_DBFILE);
  MoveFile(pszInstallDir, UP_INI_CONTROLS_TEMP, UP_INI_CONTROLS);
  MoveFile(pszInstallDir, UP_INI_EVENTS_TEMP, UP_INI_EVENTS);
  MoveFile(pszInstallDir, UP_INI_LIBRARY_TEMP, UP_INI_LIBRARY);
  MoveFile(pszInstallDir, UP_INI_PODCASTS_TEMP, UP_INI_PODCASTS);
  MoveFile(pszInstallDir, UP_INI_REGEX_TEMP, UP_INI_REGEX);
  MoveFile(pszInstallDir, UP_INI_SETTINGS_TEMP, UP_INI_SETTINGS);
  MoveFile(pszInstallDir, UP_INI_STATE_TEMP, UP_INI_STATE);
  MoveFile(pszInstallDir, UP_CACHE_MUSIC_TEMP, UP_CACHE_MUSIC);
  MoveFile(pszInstallDir, UP_CACHE_PODCAST_TEMP, UP_CACHE_PODCAST);
  MoveFile(pszInstallDir, UP_CACHE_RADIO_TEMP, UP_CACHE_RADIO);
  MoveFile(pszInstallDir, UP_CACHE_EDITOR_TEMP, UP_CACHE_EDITOR);
  MoveFile(pszInstallDir, UP_ERROR_LOG_TEMP, UP_ERROR_LOG);
}

bool IsUpgrading(LPCTSTR pszInstallDir)
{
  wchar_t path[MAX_PATH+1];
  _tcscpy(path, pszInstallDir);
  _tcscat(path, UPGRADEFILE);
  WIN32_FIND_DATA fd;
  HANDLE hf = FindFirstFileEx(path, FindExInfoStandard, &fd, FindExSearchNameMatch, NULL, 0);
  if (hf != INVALID_HANDLE_VALUE)
  {
    FindClose(hf);
    return true;
  }
  return false;
}


BOOL APIENTRY DllMain(HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
  return TRUE;
}

codeINSTALL_INIT Install_Init(HWND hwndParent, BOOL fFirstCall, BOOL fPreviouslyInstalled, LPCTSTR pszInstallDir)
{
  if (fFirstCall && fPreviouslyInstalled)
  {
    SetUpgrade(pszInstallDir);
  }
  return codeINSTALL_INIT_CONTINUE;
}

codeINSTALL_EXIT Install_Exit(HWND hwndParent, LPCTSTR pszInstallDir, WORD cFailedDirs, WORD cFailedFiles, WORD cFailedRegKeys, WORD cFailedRegVals, WORD cFailedShortcuts)
{
  TCHAR szFullMultiCabPath[MAX_PATH];

  if (IsUpgrading(pszInstallDir))
  {
    UnsetUpgrade(pszInstallDir);
  }

  if (!IsSQLCEUpdateRequired()) 
  {
    // DeleteSQLCABs((LPTSTR)pszInstallDir); // Don't delete this file here in case we are using an old version of SQL CE and need to update it
    DeleteFile(pszInstallDir, L"\\multicab.exe");
    CleanupAppRegKey(L"Software\\Avian Waves", L"Avian Play");
    CleanupAppRegKey(L"Software\\Avian Waves", L"Avian Play Cabs");
  }
  else
  {
    MessageBox(hwndParent, L"Avian Play Setup has detected that SQL CE 3.5 or newer is not installed.  The SQL CE 3.51 SP2 CAB will be launched automatically after the setup screen is closed.", L"Avian Play Setup", MB_OK);

    StringCchPrintf(szFullMultiCabPath, ARRAYSIZE(szFullMultiCabPath), TEXT("%s\\multicab.exe"), pszInstallDir);

    SHELLEXECUTEINFO sei = {0};
    sei.cbSize = sizeof(sei);
    sei.nShow = SW_SHOWNORMAL;

    sei.lpFile = szFullMultiCabPath;
    ShellExecuteEx(&sei);
  }

  return codeINSTALL_EXIT_DONE;
} 

codeUNINSTALL_INIT Uninstall_Init(HWND hwndParent, LPCTSTR pszInstallDir)
{
  if (!IsUpgrading(pszInstallDir) && MessageBox(hwndParent, L"Would you like to keep your settings and database? (Do this if you want to preserve settings for a future installation.)", L"Avian Play Setup", MB_YESNO) == IDYES)
  {
    SetUpgrade(pszInstallDir);
  }

  return codeUNINSTALL_INIT_CONTINUE;
} 

codeUNINSTALL_EXIT Uninstall_Exit(HWND hwndParent)
{
  return codeUNINSTALL_EXIT_DONE;
}
